#include "AbstractShapeItem.h"
#include "NodeInPort.h"
#include "NodeOutPort.h"
#include "xMappingNode.h"
#include "xInMappingPort.h"
#include "xOutMappingPort.h"

#include <QtGui/QPen>

AbstractShapeItem::AbstractShapeItem( string name, AbstractManager* manager, QGraphicsItem *parent)
	: Item(manager), QAbstractGraphicsShapeItem (parent)
{
	this->_name = name;
	this->_nodeType = -1;
	this->_width = 0;
	this->_bodyHeight = 0;
}


AbstractShapeItem::~AbstractShapeItem(void)
{
}

void AbstractShapeItem::setBodyHeight( int height )
{
	this->_bodyHeight = height;
}

xMappingNode* AbstractShapeItem::getMappingNode() const {
	return this->_mpnNode;
}

std::string AbstractShapeItem::getName() const {
	return this->_name;
}

const std::vector<NodeInPort*>& AbstractShapeItem::getInportList() const {
	return this->_inportList;
}

const std::vector<NodeOutPort*>& AbstractShapeItem::getOutportList() const {
	return this->_outportList;
}

int AbstractShapeItem::height()
{
	return this->_bodyHeight;
}

NodeInPort* AbstractShapeItem::addInPort()
{
	if( this->getMappingNode()->getNodeTypePtr()->getInportFixed() )
		return NULL;

	xInMappingPort* ref = this->getMappingNode()->getInports().at(0);
	xInMappingPort* imp = _mpnNode->newInPort( ref->getName(), ref->getType(), CLASS_REQUIRED, "NULL", ref->getCategory() );

	// 標示這是第幾個變數
	if (this->_name =="math"){
		std::ostringstream oss;
		oss << trf(imp->getType()) << " $" << _inportList.size();
		imp->setName(oss.str());
	}

	NodeInPort* inport=new NodeInPort(imp,this);
	_inportList.push_back(inport);

	return inport;
}

NodeOutPort* AbstractShapeItem::addOutPort()
{
	if( this->getMappingNode()->getNodeTypePtr()->getOutportFixed() )
		return NULL;

	xOutMappingPort* ref = this->getMappingNode()->getOutports().at(0);
	xOutMappingPort* omp = _mpnNode->newOutPort( ref->getName(), ref->getType(), CLASS_REQUIRED, "NULL", ref->getCategory() );
	NodeOutPort* outport = new NodeOutPort(omp, this);
	_outportList.push_back(outport);

	return outport;
}

void AbstractShapeItem::deleteInPort( NodeInPort* inPort )
{
	if( this->getMappingNode()->getNodeTypePtr()->getInportFixed() )
		return;
	
	vector<NodeInPort*>::iterator itr;
	int i = 0;

	for ( itr = _inportList.begin(); itr != _inportList.end(); ++itr) {
		if ( *itr == inPort){
			delete *itr;
			_inportList.erase(itr);
			_mpnNode->deletePort(i);
			break;
		}
		i++;
	}
}


void AbstractShapeItem::deleteOutPort( NodeOutPort* outPort)
{
	if( this->getMappingNode()->getNodeTypePtr()->getOutportFixed() )
		return;

	vector<NodeOutPort*>::iterator itr;
	int i = 0;

	for ( itr = _outportList.begin(); itr != _outportList.end(); ++itr) {
		if ( *itr == outPort){
			delete *itr;
			_outportList.erase(itr);
			_mpnNode->deletePort(i);
			break;
		}
		i++;
	}
}



int AbstractShapeItem::width()
{
	return this->_width;
}

int AbstractShapeItem::nodeType()
{
	return this->_nodeType;
}

void AbstractShapeItem::deleteEmptyInPort()
{
	if( this->getMappingNode()->getNodeTypePtr()->getInportFixed() )
		return;

	int i=0;
	vector<NodeInPort*>::iterator itr=_inportList.begin();
	while(itr!=_inportList.end()){
		if(!(*itr)->isConnected()){
			_mpnNode->deletePort(i);
			delete *itr;
			_inportList.erase(itr);
			itr=_inportList.begin();
			i=0;
			continue;
		}
		itr++;
		i++;
	}
}

void AbstractShapeItem::deleteEmptyOutPort()
{
	if( this->getMappingNode()->getNodeTypePtr()->getOutportFixed() )
		return;

	int i=0;
	vector<NodeOutPort*>::iterator itr=_outportList.begin();
	while(itr!=_outportList.end()){
		if(!(*itr)->isConnected()){
			_mpnNode->deletePort(i);
			delete *itr;
			_outportList.erase(itr);
			itr=_outportList.begin();
			i=0;
			continue;
		}
		itr++;
		i++;
	}
}

void AbstractShapeItem::setBackgroundColor( const QColor &color )
{
	_backgroundColor->setColor(color);
}

void AbstractShapeItem::setFontColor( const QColor &color )
{
	_fontColor->setColor(color);
}

void AbstractShapeItem::setForeachElements( bool b )
{
	_mpnNode->setForeachElements(b);
	this->update();
}

bool AbstractShapeItem::isForeachElements() const {
	return _mpnNode->isForeachElements();
}
